package busuanzi.storage;

import busuanzi.util.Sugars;
import com.alibaba.fastjson.JSON;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;

/**
 * Auth: bruce-sha
 * Date: 2015/4/22
 * <p/>
 * http://mongodb.github.io/mongo-java-driver/3.0/
 */
public class MongoClient {

    static private com.mongodb.MongoClient client;

    private static com.mongodb.MongoClient get() {
        if (client == null) {
            // client = new com.mongodb.MongoClient(new MongoClientURI("mongodb://localhost:27017"));
            client = new com.mongodb.MongoClient(new ServerAddress("localhost", 27017)/*, Arrays.asList(
                    MongoCredential.createCredential("bao", "buru", "12345678".toCharArray()),
                    MongoCredential.createCredential("buru", "admin", "buru.mongodb".toCharArray()),
                    MongoCredential.createCredential("buru", "busuanzi", "buru.mongo".toCharArray()))*/);
        }
        return client; // return client.getDatabase("busuanzi");
    }

    public static class MongoHelper {
        private String databaseAndCollectionName;

        public <T> T bath(MongoBather bather) {
            assert databaseAndCollectionName != null;

            final String[] ns = databaseAndCollectionName.split("/", 2);
            final com.mongodb.MongoClient client = get();
            final MongoDatabase mongoDatabase = client.getDatabase(ns[0]);
            final MongoCollection<Document> mongoCollection = mongoDatabase.getCollection(ns[1]);
            return (T) bather.bath(mongoCollection);
        }

        public void wash(MongoWasher washer) {
            bath(mongoCollection -> {
                washer.wash(mongoCollection);
                return Sugars.VOID;
            });
        }
    }

    public static MongoHelper collection(String databaseAndCollectionName) {
        MongoHelper helper = new MongoHelper();
        helper.databaseAndCollectionName = databaseAndCollectionName;
        return helper;
    }

    public static <T> T bath(String databaseAndCollectionName, MongoBather bather) {
        return collection(databaseAndCollectionName).bath(bather);
    }

    public interface MongoBather {
        Object bath(MongoCollection<Document> mongoCollection);
    }

    public static void wash(String databaseAndCollectionName, MongoWasher washer) {
        collection(databaseAndCollectionName).wash(washer);
    }

    public interface MongoWasher {
        void wash(MongoCollection<Document> mongoCollection);
    }

    public static Document newDocument(Object... kvs) {
        int length = kvs.length;
        assert length % 2 == 0;

        final Document doc = new Document();
        for (int i = 0; i < length; i = i + 2) {
            doc.append(kvs[i].toString(), kvs[i + 1]);
        }

        return doc;
    }

    public static Document s(String shellTemplate, Object... args) {
        return Document.parse(String.format(shellTemplate, args));
    }

    public static void main(String[] args) {
        String busuanziToken = "sadsdf";
        Document d0 = s("{token:'%s'}", busuanziToken);

        Document d0ee = s("{age: {$gt: 18}}", busuanziToken);

        Document d = newDocument("age", newDocument("$gt", 18));

        Object o = JSON.parse("{age: {'$gt': 18}}");

        Document d3 = Document.parse("{age: {$gt: 18}}");

        System.out.println(o);

    }

    public static Document newUpdateDocument(Object... kvs) {
        return newDocument("$set", newDocument(kvs));
    }
}
